/**
 * 
 */
package fhq.hcmute.edu.vn.gestures;

import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;

/**
 * @author Hien Nguyen Oct 24, 2012
 */
public class MyGestures {

	private static final int FINGER_ID_TWO = 1;
	private static final int FINGER_ID_ONE = 0;
	private static final int ONE_POINTER = 1;
	private static final int TWO_POINTERS = 2;
	public static final int NONE = 10000;
	public static final int MOVE = 10001;
	public static final int TAP = 10002;
	public static final int DOUBLE_TAP = 10003;
	public static final int DROP = 10004;
	public static final int DRAP = 10005;
	public static final int LONG_PRESS = 10006;
	public static final int ZOOM = 20000;
	public static final int ZOOM_IN = 20001;
	public static final int ZOOM_OUT = 20002;
	public static final int SCROLL_UP = 30001;
	public static final int SCROLL_DOWN = 30002;
	private TouchManager touchManager;
	private static final int TIME_DELAY = 100;
	private static final float OFFSET = 0.2F;

	public MyGestures(TouchManager touchManager) {
		this.touchManager = touchManager;
	}

	private long timeDown;
	private long timeUp;
	private int scrollCount = 0;
	private int moveCount = 0;
	private int zoomCount = 0;
	private int previousGesture = NONE;

	public int getGestures() {
		int pointerCoint = touchManager.getMotionEvent().getPointerCount();
		if (pointerCoint == ONE_POINTER) {
			switch (touchManager.getAction()) {
			case MotionEvent.ACTION_DOWN: {
				timeDown = SystemClock.elapsedRealtime();
				if (previousGesture == TAP &&
						(timeDown - timeUp) <= TIME_DELAY) {
					previousGesture = DROP;
					Log.v("nglehien", "DROP");
					return DROP;
				}
				break;
			}
			case MotionEvent.ACTION_UP: {
				timeUp = SystemClock.elapsedRealtime();
				Log.v("nglehien", "ACTION_UP-" + previousGesture);
				if ((timeUp - timeDown) <= TIME_DELAY) {
					previousGesture = TAP;
					return TAP;
				} else {
					previousGesture = NONE;
					return DRAP;
				}
			}
			case MotionEvent.ACTION_MOVE: {
				if (moveCount == 5) {
					scrollCount = 0;
					previousGesture = MOVE;
					return MOVE;
				}
				scrollCount = 0;
				zoomCount = 0;
				moveCount++;
				break;
			}
			}
		} else if (pointerCoint == TWO_POINTERS) {
			if (touchManager.getAction() == MotionEvent.ACTION_MOVE) {
				TouchPoint fixedPoint = touchManager.getFixedTouchPoint();
				float fixedPointLength = fixedPoint.getLength();
				TouchPoint currentPoint = touchManager.getCurrentTouchPoint();
				float currentPointLength = currentPoint.getLength();
				TouchPoint previousPoint = touchManager.getPreviousTouchPoint();
				float previousPointLength = previousPoint.getLength();
				// detect scroll event.
				if (isAppropriate(currentPointLength / fixedPointLength, 1.0F,
						OFFSET)) {
					float xMoveF1 = touchManager.getXMove(0);
					float xMoveF2 = touchManager.getXMove(1);
					if (Math.abs(xMoveF1 - xMoveF2) <= 5) {
						if (scrollCount == 5) {
							scrollCount = 0;
							TouchPoint tca = touchManager
									.getCurrentTouchPointAt(FINGER_ID_ONE);
							TouchPoint tpa = touchManager
									.getPreviousTouchPointAt(FINGER_ID_ONE);
							TouchPoint tcb = touchManager
									.getCurrentTouchPointAt(FINGER_ID_TWO);
							TouchPoint tpb = touchManager
									.getPreviousTouchPointAt(FINGER_ID_TWO);
							if ((tca.getY() > tpa.getY())
									&& (tcb.getY() > tpb.getY())) {
								previousGesture = SCROLL_DOWN;
								return SCROLL_DOWN;
							} else if ((tca.getY() < tpa.getY())
									&& (tcb.getY() < tpb.getY())) {
								previousGesture = SCROLL_UP;
								return SCROLL_UP;
							}
						}
						moveCount = 0;
						zoomCount = 0;
						scrollCount++;
					} else {
						moveCount = 0;
						scrollCount = 0;
					}
				} else {
					float scale = currentPointLength / previousPointLength;
					if (zoomCount == 5) {
						if (scale > 1.0F) {
							zoomCount = 0;
							previousGesture = ZOOM_IN;
							return ZOOM_IN;
						} else if (scale < 1.0F) {
							zoomCount = 0;
							previousGesture = ZOOM_OUT;
							return ZOOM_OUT;
						}
					}
					zoomCount++;
					moveCount = 0;
					scrollCount = 0;
				}
			}
		}
		return NONE;
	}

	private boolean isAppropriate(float x, float rate, float offset) {
		if ((x > (rate - offset)) && (x < (rate + offset))) {
			return true;
		}
		return false;
	}

	/**
	 * @return the previousGesture
	 */
	public int getPreviousGesture() {
		return previousGesture;
	}

	/**
	 * @param previousGesture
	 *            the previousGesture to set
	 */
	public void setPreviousGesture(int previousGesture) {
		this.previousGesture = previousGesture;
	}
}
